package com.adxon.data;

import com.adxon.MsgException;
import com.adxon.servlet.ServletBase;

import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

public class Base{
	private static class Conn{
		private final static int SLT=4;

		Connection	c;
		int			i;
		int			m;
		String		d="jdbc:mysql://w.rdc.sae.sina.com.cn:3307/app_mytest01";
		String		u="w5yj2myxwk";
		String		p="l04zz2k0lh4ymhhyk5kkk4555w5zyw0x0whk0i0l";

		private int id()throws MsgException{
			try{
				if(i>=m){
					System.out.print("* ");
					Statement s=c.createStatement();
					s.executeUpdate("UPDATE k SET i=LAST_INSERT_ID(i+1)",
							Statement.RETURN_GENERATED_KEYS);
					ResultSet r=s.getGeneratedKeys(); 
					if(r.next()){
						i=r.getInt(1)*SLT;
						m=i+SLT;
					}
					r.close();
					s.close();
				}
				System.out.println(i+"/"+m);
				return ++i+ServletBase.site;
			}catch(SQLException e){
				throw new MsgException(MsgException.SQL,null,e.getMessage());
			}
		}
	}

	private static ThreadLocal<Conn>	con=initConn(); 

	private static Conn conn(){
		try{
			Conn r=con.get();
			if(r==null){
				r=new Conn();
				r.c=DriverManager.getConnection(r.d,r.u,r.p);
				con.set(r);
			}
			return r;
		}catch(SQLException e){
			e.printStackTrace();
			return null;
		}
	}
	public static Connection connect(){
		return conn().c;
	}
	private static ThreadLocal<Conn> initConn(){
		try{
			Class.forName("com.mysql.jdbc.Driver");
			return new ThreadLocal<Conn>(); 
		}catch(ClassNotFoundException e){
			e.printStackTrace();
			return null; 
		}
	}
	public static void main(String[] args){
		try{
			Item e;
			e=new Item();
			e.setText("Tes0");
			e.commit();
			e.setDescription("text");
			e.commit();
			long i=e.getId();
			System.out.println(i);
			e=new Item();
			e.update(i);
			System.out.println(e.getText());
		}catch(MsgException e){
			e.printStackTrace();
		}
	}
	public final static String regulate(String string){
		if(string!=null){
			string=string.trim();
			if(string.length()==0)
				string=null;
		}
		return string;
	}

	protected String				bsk;		// base kind
	protected Map<String,Object>	col;		// columns
	protected boolean				flg=true;	// flag
	protected long					id;			// id
	protected String				ins;		// insert values
	protected Map<String,Object>	key;		// keys
	private ResultSet				res;		// result set
	protected String				set;		// set values
	protected String				stp;		// columns for setup
	protected boolean				upd;		// update
	protected String				whr;		// where values

	protected void allocateId()throws MsgException{
		id=conn().id();
	}
	public void commit()throws MsgException{
		if(flg)try{
			if(id==0)
				allocateId();
			col=new TreeMap<String,Object>();
			key=new TreeMap<String,Object>();
			commitExt();
			if(set==null){
				StringBuilder i=new StringBuilder();
				StringBuilder s=new StringBuilder();
				StringBuilder w=new StringBuilder();
				String p="";
				for(String e:col.keySet()){
					s.append(p);
					s.append(e);
					s.append("=?");
					p=",";
				}
				String a="";
				p="";
				for(String e:key.keySet()){
					i.append(p);
					i.append(e);
					i.append("=?");
					w.append(a);
					w.append(e);
					w.append("=?");
					p=" AND ";
					p=",";
				}
				ins=i.toString();
				set=s.toString();
				whr=w.toString();
			}
			String q=upd?("UPDATE "+bsk+" SET "+set+" WHERE "+whr):
				("INSERT "+bsk+" SET "+set+','+ins);
			System.out.println(id+": "+q);
			PreparedStatement s=conn().c.prepareStatement(q);
			int n=1;
			for(Object e:col.values()){
				if(e==null)
					s.setObject(n,null);
				else{
					String c=e.getClass().getSimpleName();
					if(c.equals("Byte"))
						s.setByte(n,(Byte)e);
					else if(c.equals("Integer"))
						s.setInt(n,(Integer)e);
					else if(c.equals("Long"))
						s.setLong(n,(Long)e);
					else if(c.equals("String"))
						s.setString(n,(String)e);
				}
				n++;
			}
			s.setLong(n,id);
			s.executeUpdate();
			s.close();
			upd=true;
		}catch(SQLException e){
			throw new MsgException(MsgException.SQL,null,e.getMessage());
		}
	}
	protected void commit(String column,byte value){
		col.put(column,value);
	}
	protected boolean commit(String column,byte[] value){
		if(value==null)
			return false;
		col.put(column,value);
		return true;
	}
	protected void commit(String column,int value){
		col.put(column,value);
	}
	protected void commit(String column,long value){
		col.put(column,value);
	}
	protected void commit(String column,String value){
		col.put(column,value);
	}
	protected void commitExt()throws MsgException{
		this.setKey("id",id);
	}
	public boolean equals(Base base){
		return base.id==id;
	}
	public void getAll(HttpServletRequest req){
		req.setAttribute("i",this);
	}
	public long getId(){
		return id;
	}
	public void getInfo(HttpServletRequest req)throws MsgException{
		getAll(req);
		req.setAttribute("Page","info.jsp");
	}
	public void getPage(HttpServletRequest req)throws MsgException{
		getAll(req);
		req.setAttribute("Page","page.jsp");
	}
	public void getPost(HttpServletRequest req)throws MsgException{
		getAll(req);
		req.setAttribute("Page","post.jsp");
	}
	public void reset(){
		id=0;
	}
	public void setAll(Base src){
		id=src.id;
		res=src.res;
	}
	public void setAll(HttpServletRequest req)throws MsgException{
	}
	public void setFlag(boolean flag){
		flg=flag;
	}
	public void setId(Base base){
		id=base.id;
	}
	public void setId(long value){
		id=value;
	}
	protected void setKey(String column,int value){
		key.put(column,value);
	}
	protected void setKey(String column,long value){
		key.put(column,value);
	}
	protected void setKey(String column,String value){
		key.put(column,value);
	}
	public void setup()throws MsgException{
		try{
			Statement s=conn().c.createStatement();
			if(stp==null){
				s.executeUpdate("DROP TABLE IF EXISTS k");
				System.out.println("CREATE TABLE k("+
						"id INT NOT NULL AUTO_INCREMENT,"+
						"PRIMARY KEY(id))");
				s.executeUpdate("CREATE TABLE k("+
						"i INT NOT NULL,PRIMARY KEY(i))");
				s.executeUpdate("INSERT k SET i=0");
			}else{
				s.executeUpdate("DROP TABLE IF EXISTS "+bsk);
				System.out.println("CREATE TABLE "+bsk+"("+stp+")");
				s.executeUpdate("CREATE TABLE "+bsk+"("+stp+")"+
						"ENGINE=INNODB DEFAULT CHARSET=UTF8");
			}
			s.close();
		}catch(SQLException e){
			throw new MsgException(MsgException.SQL,null,e.getMessage());
		}
	}
	@Override
	public String toString(){
		return Long.toString(id);
	}
	public final Base update()throws MsgException{
		return update(id);
	}
	public Base update(long key)throws MsgException{
		Object[] s={key};
		return update("id=?",s);
	}
	public Base update(String cond,final Object[] args)throws MsgException{
		try{
			PreparedStatement s=conn().c.prepareStatement(
					"SELECT * FROM "+bsk+" WHERE "+cond);
			ResultSet r=null;
			try{
				int n=1;
				for(Object e:args)
					s.setObject(n++,e);
				r=s.executeQuery();
				if(r.next())
					update(r);
				else throw new MsgException(MsgException.NOT_FOUND,null);
			}finally{
				if(r!=null)
					r.close();
				s.close();
			}
		}catch(SQLException e){
			throw new MsgException(MsgException.SQL,null,e.getMessage());
		}
		return this;
	}
	public Base update(ResultSet resultSet)throws MsgException{
		flg=false;
		res=resultSet;
		updateExt();
		upd=true;
		return this;
	}
	protected Blob updateBlob(String column)throws MsgException{
		try{
			return res.getBlob(column);
		}catch(SQLException e){
			throw new MsgException(MsgException.SQL,null,e.getMessage());
		}
	}
	protected byte updateByte(String column)throws MsgException{
		try{
			return res.getByte(column);
		}catch(SQLException e){
			throw new MsgException(MsgException.SQL,null,e.getMessage());
		}
	}
	protected void updateExt()throws MsgException{
		id=updateLong("id");
	}
	protected int updateInt(String column)throws MsgException{
		try{
			return res.getInt(column);
		}catch(SQLException e){
			throw new MsgException(MsgException.SQL,null,e.getMessage());
		}
	}
	protected long updateLong(String column)throws MsgException{
		try{
			return res.getLong(column);
		}catch(SQLException e){
			throw new MsgException(MsgException.SQL,null,e.getMessage());
		}
	}
	protected String updateString(String column)throws MsgException{
		try{
			return res.getString(column);
		}catch(SQLException e){
			throw new MsgException(MsgException.SQL,null,e.getMessage());
		}
	}
}